package com.snailhd.framework.jdbc.mybatis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.util.StringUtils;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 *
 * @author snailhd
 */
public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> {

    private TypeReference<T> typeReference;

    public JsonTypeHandler() {
    }

    public JsonTypeHandler(Class<T> clazz) {
        typeReference = new TypeReference<T>() {};
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ObjectMapper mapper = new ObjectMapper();
        try{
            if(parameter==null){
                return;
            }
            ps.setString(i,mapper.writeValueAsString(parameter));
        }catch (JsonProcessingException e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        try {
            return parseObj(rs.getString(columnName), typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        try {
            return parseObj(rs.getString(columnIndex), typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

        try {
            return parseObj(cs.getString(columnIndex), typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public T parseObj(String text, TypeReference<T> typeReference) throws JsonProcessingException {
        if(StringUtils.isEmpty(text) || StringUtils.isEmpty(text.trim())){
            return null;
        }else {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(text, typeReference);
        }
    }
}
